#!/usr/bin/env python
# Copyright 2005,2006 Michael Rice
# errr@errr-online.com

""" fluxStyle

fluxStyle is a graphical style-manager for the fluxbox
window manager. Orignal version written by Michael Rice.
Many special thanks to Zan a.k.a. Lauri Peltonen for GUI
Improvements & Bug Stomping.

Released under GPL v2.

TODO
- somehow support older styles and not put folders in the list
  like folders that dont have anything to do with a style.
- fix any bugs that may still be there and unseen..
- add tray icon support (this is started will be done soon)
"""
import os
import gtk
import gtk.glade
from fluxstyle import find_styles, parse_config
from os.path import isfile,expanduser,isdir
from fluxstyle import error_message

#GLADEFILE="/usr/share/fluxstyle/glade/main.glade"
#N_IMAGE="/usr/share/fluxstyle/images/none.jpg"
GLADEFILE="./glade/main.glade"
N_IMAGE="./images/none.jpg"

class StyleChange:
    """Class wrapper for changing styles in fluxbox"""
    location = ""
    def main(self):
        gtk.main()

    def __init__(self):
        """The main fluxStyle window will show"""
        windowname = "window1"
        self.wTree = gtk.glade.XML (GLADEFILE,windowname)
        self.treeview1 = self.wTree.get_widget("treeview1")
        self.view_menu = self.wTree.get_widget("view1_menu")
        self.__fill_view_menu__(self.view_menu)

        handler = {"on_apply_style_clicked":self.__apply_style_clicked__,
                "on_quit_clicked":(gtk.main_quit),
                "on_add_style_clicked":self.__add_style_clicked__,
                "on_remove_style_clicked":self.__remove_style_clicked__,
                "on_quit1_activate":(gtk.main_quit),
                "on_about1_activate":self.__about1_activate__,
                "on_window1_destroy":(gtk.main_quit),
                "on_default1_activate":self.__fill_combolist__}

        self.wTree.signal_autoconnect (handler)

        #Preparing the treeview here
        self.liststore = gtk.ListStore(gtk.gdk.Pixbuf, str)
        self.treeview1.set_model(self.liststore)

        renderer = gtk.CellRendererText()
        imagerenderer = gtk.CellRendererPixbuf()
        imagerenderer.set_property('ypad', 10)
        imagerenderer.set_property('xpad', 5)
        column1 = gtk.TreeViewColumn("Preview", imagerenderer, pixbuf=0)
        column1.set_resizable(True)
        column2 = gtk.TreeViewColumn("Name", renderer, text=1)
        column2.set_resizable(True)
        self.treeview1.append_column(column1)
        self.treeview1.append_column(column2)

        #Fill it (Clear + fill)
        self.__fill_combolist__(self.treeview1,loc="default")
        return

    # Call backs begin here
    # fill combo list
    def __fill_combolist__(self,widget,loc="default"):
        """Fill the combo list with styles test to see if there is a
        ~/.fluxbox/styles if there isnt then make it and move on."""
        self.location = expanduser(loc)
        if self.location == "default":
            self.location = expanduser("~/.fluxbox/styles")
            try:
                dir = os.listdir(self.location)
                dir.sort()
                self.liststore.clear()
                for styles in dir:
                    self.liststore.append((self.__get_preview__(styles), 
                        styles,))
            except(OSError):
                dir = expanduser("~/.fluxbox/styles")
                os.makedirs(dir,mode=0700)
                message = """You did not have a default style folder. One has 
                been created for you. The list will remain empty until you
                install a style which you can do by clicking the add button.
                """
                error_message.info_message(message)
        else:
            try:
                dir = os.listdir(self.location)
                dir.sort()
                self.liststore.clear()
                for styles in dir:
                    self.liststore.append((self.__get_preview__(styles), 
                        styles,))
            except(OSError):
                m = """You have an invalid location in your ~/.fluxStyle.rc
                file. It is possible that you have a syntax error. Please exit
                fluxStlye and fix the error in this file and try again.
                """
                error_message.info_message(m)

    # get the preview image for view
    def __get_preview__(self, stylename):
        """Get the preview image from: location + /styleName/preview.jpg"""
        self.location = expanduser(self.location)
        image = gtk.Image()
        if isdir(self.location + "/" + stylename):
            if isfile(self.location+"/"+stylename+"/preview.jpg"):
                image.set_from_file(self.location+"/" +stylename+"/preview.jpg")
            else:
                image.set_from_file(N_IMAGE)
        return image.get_pixbuf()

    def __fill_view_menu__(self, widget):
        if parse_config.check4_config() == 2:
            message = """First run detected. A default config has been created
            for you. You should edit this config to control the location of
            styles shown in the preview window. The config file is located in
            ~/.fluxStyle.rc"""
            error_message.info_message(message)

        elif parse_config.check4_config() == 3:
            message = """You do not have the config file ~/.fluxStyle.rc and
            you do not have write access to your $HOME directory.""" 
            error_message.info_message(message)
        
        elif parse_config.check4_config() == True:
            ops = parse_config.parse_file(expanduser("~/.fluxStyle.rc"))
            l = []
            if ops != False:
                count = 1
                view = self.view_menu
                for k,v in ops.iteritems():
                    if k == "STYLES_DIRS":
                        for x in v:
                            l.append(x.strip().split(','))
                        for i in l:
                            if len(i) <= 1:
                                name = "_"+str(count)+" %s"%(" Extra Styles")
                                menuitem = gtk.MenuItem(name + str(count))
                                menuitem.connect("activate", 
                                        self.__fill_combolist__,
                                        i[0])
                                view.add(menuitem)
                                count += 1
                            else:
                                name = "_%s"%(i[0])
                                menuitem = gtk.MenuItem(name)
                                menuitem.connect("activate",
                                        self.__fill_combolist__,
                                        i[1])
                                view.add(menuitem)
                                view.show_all()
    # Set style
    def __apply_style_clicked__(self,widget):
        """Used to apply new styles"""
        style = self.__get_selected_style__()
        if style:
            find_styles.set_style(style,self.location)

    # Add style
    def __add_style_clicked__(self,widget):
        """Install a new style, multiple styles can be installed at once."""

        dialog = gtk.FileChooserDialog("Choose file to install",
                None,gtk.FILE_CHOOSER_ACTION_OPEN,
                (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
                gtk.STOCK_OPEN, gtk.RESPONSE_OK))
        dialog.set_default_response(gtk.RESPONSE_OK)
        filter = gtk.FileFilter()
        filter.set_name("Fluxbox Styles")
        filter.add_mime_type("tar/gz")
        filter.add_mime_type("tar/bz2")
        filter.add_pattern("*.tar.gz")
        filter.add_pattern("*.tar.bz2")
        filter.add_pattern("*.tgz")
        dialog.add_filter(filter)
        dialog.set_select_multiple(True)

        response = dialog.run()
        if response == gtk.RESPONSE_OK:
            find_styles.install_style(dialog.get_filenames())
            self.__fill_combolist__(self)
            dialog.destroy()
        if response == gtk.RESPONSE_CANCEL:
            dialog.destroy()

    # remove style
    def __remove_style_clicked__(self,widget):
        """Remove selected style"""
        style = self.__get_selected_style__()
        if style == False:
            m = "You must select a style to remove first"
            error_message.info_message(m)
        else:
            message = gtk.MessageDialog(None, 
                    gtk.DIALOG_MODAL, 
                    gtk.MESSAGE_INFO,
                    gtk.BUTTONS_NONE, 
                    "Are you sure you want to delete {0}?".format(style))
            message.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
            message.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CLOSE)
            response = message.run()
            message.hide()
            if response == gtk.RESPONSE_OK:
                if find_styles.remove_style(style,self.location) != False:
                    message.destroy()
                    self.__fill_combolist__(self,self.location)
                else:
                    say = """You do not have access to remove this style Please
                    contact your system admin for help removing this style.
                    """
                    message = gtk.MessageDialog(None,
                            gtk.DIALOG_MODAL,
                            gtk.MESSAGE_INFO,
                            gtk.BUTTONS_NONE,
                            say)
                    message.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)
                    response = message.run()
                    message.hide()
                if response == gtk.RESPONSE_CLOSE:
                    message.destroy()
            if response == gtk.RESPONSE_CLOSE:
                message.destroy()

    def __get_selected_style__(self):
        """Getting the selected style"""
        selection = self.treeview1.get_selection()
        (model, iter) = selection.get_selected()
        if model and iter:
            return model.get_value(iter, 1)
        else:
            return False

    def __close_about__(self,widget,event):
        """close about dialog"""
        if event == gtk.RESPONSE_CANCEL:
            self.aboutdialog.destroy()

    def __about1_activate__(self,widget):
        """Activate the help button with the about dialog,
        use generic if pygtk < 2.5.9
        """
        if gtk.pygtk_version < (2,5,90):
            message = """Update your pygtk version for more features.
            Version 2.6.0 or newer is reccomended.
            """
            error_message.info_message(message)
        else:
            windowname2="aboutdialog1"
            self.wTree2=gtk.glade.XML (GLADEFILE,windowname2)
            handler = { "on_aboutdialog1_response":self.__close_about__}
            self.wTree2.signal_autoconnect(handler)
            self.aboutdialog = self.wTree2.get_widget("aboutdialog1")

if __name__ == "__main__":
    style = StyleChange()
    style.main()
